home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / usq.c < prev    next >
Text File  |  1985-06-12  |  6KB  |  300 lines

  1. static char *sccsid = "@(#)usq.c        1.7u (UCF) 82/12/15";
  2. /*
  3.  * usq.c - CP/M compatible file unsqueezer utility
  4.  *
  5.  *compile as follows:
  6.  *cc [-DVAX] -O usq.c -o usq
  7.  *   (define VAX only if running on VAX)
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <signal.h>
  12. #include <ctype.h>
  13.  
  14. #define TRUE 1
  15. #define FALSE 0
  16. #define ERROR (-1)
  17. #define PATHLEN312/* Number of characters allowed in pathname */
  18. #define OK 0
  19.  
  20. #define RECOGNIZE 0xFF76/* unlikely pattern */
  21. #define DLE 0x90/* repeat byte flag */
  22. #define SPEOF 256/* special endfile token */
  23. #define NUMVALS 257/* 256 data values plus SPEOF*/
  24. #define LARGE 30000
  25.  
  26. #ifdef VAX   /* then we don't want 32 bit integers */
  27.  
  28. typedef short INT;
  29. typedef unsigned short UNSIGNED;
  30.  
  31. #else   /*  16 bit machines  */
  32.  
  33. typedef int INT;
  34. typedef unsigned UNSIGNED;
  35.  
  36. #endif
  37.  
  38. struct _sqleaf {/* Decoding tree */
  39. INT _children[2];/* left, right */
  40. };
  41. struct _sqleaf Dnode[NUMVALS - 1];
  42.  
  43.  
  44. INT Bpos;/* last bit position read */
  45. INT Curin;/* last byte value read */
  46. INT Repct;/* Number of times to return value */
  47. INT Value;/* current byte value or EOF */
  48.  
  49. INT MakeLCPathname=TRUE;/* translate pathname to lc if all caps */
  50. INT Nlmode=FALSE;/* zap cr's if true */
  51. INT Inbackground = FALSE;
  52.  
  53. INT getcr(), getuhuff(), portgetw();
  54.  
  55. main(argc, argv)
  56. char *argv[];
  57. {
  58. register char *cp;
  59. register INT npats=0;
  60. char **patts;
  61. INT n, errorstat;
  62.  
  63. if (signal(SIGINT, SIG_IGN)==SIG_IGN)
  64. Inbackground++;
  65. else
  66. signal(SIGINT, SIG_DFL);
  67. signal(SIGHUP, SIG_IGN);
  68. errorstat=0;
  69. if(argc<2)
  70. goto usage;
  71. while (--argc) {
  72. cp = *++argv;
  73. if(*cp == '-') {
  74. while( *++cp) {
  75. switch(*cp) {
  76. case 'n':
  77. Nlmode=TRUE; break;
  78. case 'u':
  79. MakeLCPathname=FALSE; break;
  80. default:
  81. goto usage;
  82. }
  83. }
  84. }
  85. else if( !npats && argc>0) {
  86. if(argv[0][0]) {
  87. npats=argc;
  88. patts=argv;
  89. }
  90. }
  91. }
  92. if(npats < 1) {
  93. usage:
  94. fprintf(stderr,"Usage: usq [-nu] file ...\n");
  95. fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
  96. fprintf(stderr,"\t-u preserve Uppercase pathnames\n");
  97. exit(1);
  98. }
  99. for(n=0; n<npats; ++n)
  100. errorstat |= squeeze(patts[n]);
  101. exit(errorstat != 0);
  102. }
  103.  
  104. /*
  105. The following code is primarily from typesq.c and utr.c.  Typesq
  106. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  107. to typesq) were made by Bob Mathias, I am responsible for the butchery
  108. done to make it work with cat.
  109.  
  110. */
  111.  
  112. FILE *in, *out;
  113. squeeze(fname)
  114. char *fname;
  115. {
  116. register INT i, c;
  117. register char *p;
  118. register INT numnodes;/* size of decoding tree */
  119. register UNSIGNED crc;
  120. UNSIGNED filecrc;
  121. char origname[PATHLEN];/* Original file name without drive */
  122.  
  123. init_cr(); init_huff(); crc=0;
  124.  
  125. if((in=fopen( fname, "r"))==NULL) {
  126. fprintf(stderr, "usq: can't open %s\n", fname);
  127. return ERROR;
  128. }
  129. if(portgetw(in) != (INT) RECOGNIZE) {/* Process header */
  130. fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
  131. return(ERROR);
  132. }
  133. filecrc = (UNSIGNED) portgetw(in);/* checksum */
  134. p = origname;/* Get original file name */
  135. do {/* send it to array */
  136. *p = getc(in);
  137. } while(*p++ != '\0');
  138.  
  139. numnodes = portgetw(in);
  140. if(numnodes < 0 || numnodes >= NUMVALS) {
  141. fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
  142. fclose(in);
  143. return(ERROR);
  144. }
  145. /* Initialize for possible empty tree (SPEOF only) */
  146. Dnode[0]._children[0] = -(SPEOF + 1);
  147. Dnode[0]._children[1] = -(SPEOF + 1);
  148.  
  149. for(i = 0; i < numnodes; ++i) {/* Get decoding tree from file */
  150. Dnode[i]._children[0] = portgetw(in);
  151. Dnode[i]._children[1] = portgetw(in);
  152. }
  153. /* Get translated output bytes and write file */
  154. if(MakeLCPathname && !IsAnyLower(origname))
  155. uncaps(origname);
  156. for(p=origname; *p; ++p)/* change / to _ */
  157. if( *p == '/')
  158. *p = '_';
  159. if (!Inbackground)
  160. fprintf(stderr, "usq: %s -> %s\n",fname,origname);
  161. if((out=fopen(origname, "w"))==NULL) {
  162. fprintf(stderr, "usq: can't create %s\n", origname);
  163. }
  164. while ((c = getcr()) != EOF) {
  165. crc += (UNSIGNED) c;
  166. if ( c == '\r' && Nlmode)
  167. continue;
  168. putc(c, out);
  169. }
  170. fclose(in);
  171. fflush(out);
  172. fclose(out);
  173. if( crc != filecrc ) {
  174. fprintf(stderr, "usq: bad checksum in %s\n", fname);
  175. fflush(stdout);
  176. return(ERROR);
  177. }
  178. return(OK);
  179. }
  180. /*** from utr.c - */
  181. /* initialize decoding functions */
  182.  
  183. init_cr()
  184. {
  185. Repct = 0;
  186. }
  187.  
  188. init_huff()
  189. {
  190. Bpos = 99;/* force initial read */
  191. }
  192.  
  193. /* Get bytes with decoding - this decodes repetition,
  194.  * calls getuhuff to decode file stream into byte
  195.  * level code with only repetition encoding.
  196.  *
  197.  * The code is simple passing through of bytes except
  198.  * that DLE is encoded as DLE-zero and other values
  199.  * repeated more than twice are encoded as value-DLE-count.
  200.  */
  201.  
  202. INT
  203. getcr()
  204. {
  205. register INT c;
  206.  
  207. if(Repct > 0) {
  208. /* Expanding a repeated char */
  209. --Repct;
  210. return(Value);
  211. } else {
  212. /* Nothing unusual */
  213. if((c = getuhuff()) != DLE) {
  214. /* It's not the special delimiter */
  215. Value = c;
  216. if(Value == EOF)
  217. Repct = LARGE;
  218. return(Value);
  219. } else {
  220. /* Special token */
  221. if((Repct = getuhuff()) == 0)
  222. /* DLE, zero represents DLE */
  223. return(DLE);
  224. else {
  225. /* Begin expanding repetition */
  226. Repct -= 2;/* 2nd time */
  227. return(Value);
  228. }
  229. }
  230. }
  231. }
  232. /* Decode file stream into a byte level code with only
  233.  * repetition encoding remaining.
  234.  */
  235.  
  236. INT
  237. getuhuff()
  238. {
  239. register INT i;
  240.  
  241. /* Follow bit stream in tree to a leaf*/
  242. i = 0;/* Start at root of tree */
  243. do {
  244. if(++Bpos > 7) {
  245. if((Curin = getc(in)) == ERROR)
  246. return(ERROR);
  247. Bpos = 0;
  248. /* move a level deeper in tree */
  249. i = Dnode[i]._children[1 & Curin];
  250. } else
  251. i = Dnode[i]._children[1 & (Curin >>= 1)];
  252. } while(i >= 0);
  253.  
  254. /* Decode fake node index to original data value */
  255. i = -(i + 1);
  256. /* Decode special endfile token to normal EOF */
  257. i = (i == SPEOF) ? EOF : i;
  258. return(i);
  259. }
  260. /*
  261.  * Machine independent getw which always gets bytes in the same order
  262.  *  as the CP/M version of SQ wrote them
  263.  */
  264. INT
  265. portgetw(f)
  266. FILE *f;
  267. {
  268. register INT c;
  269.  
  270. c = getc(f) & 0377;
  271. return(c | (getc(f) << 8));
  272. }
  273.  
  274.  
  275. /* make string s lower case */
  276. uncaps(s)
  277. char *s;
  278. {
  279. for( ; *s; ++s)
  280. if(isupper(*s))
  281. *s = tolower(*s);
  282. }
  283.  
  284.  
  285. /*
  286.  * IsAnyLower returns TRUE if string s has lower case letters.
  287.  */
  288. IsAnyLower(s)
  289. char *s;
  290. {
  291. for( ; *s; ++s)
  292. if (islower(*s))
  293. return(TRUE);
  294. return(FALSE);
  295. }
  296.  
  297.  
  298.  
  299.  
  300.